﻿using log4net;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Timers;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;

namespace WpfApp1.Acme.ApplicationClass {
    /// <summary>
    /// Toast.xaml 的交互逻辑
    /// </summary>
    public partial class Toast : Window {
        /** 存储Toast对象 */
        private static readonly List<Toast> listToasts = new List<Toast>();
        /** Toast存储对象 */
        private static Toast toast = null;
        /** 定时器3s后调用Toast.Close()方法 */
        private static readonly Timer timer = new Timer();
        /** Toast上下文负责对Toast控件的控制 */
        private static ToastContext toastContext;
        /** Toast类型的策略池 */
        private static readonly Dictionary<ToastType, Path> toastStrategy = new Dictionary<ToastType, Path>();
        /** 日志对象 */
        private static readonly ILog logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        
        public Toast() {
            InitializeComponent();
            // 注册策略
            this.ToastContext.DataContext = toastContext;
            toastStrategy.Add(ToastType.error,this.ToastError);
            toastStrategy.Add(ToastType.info,this.ToastInfo);
        }

        /// <summary>
        /// Toast显示方法
        /// </summary>
        /// <param name="context">显示的文本</param>
        /// <param name="toastType">Toast的类型，可ToastType.Error可ToastType.Info</param>
        public static void show(in string context, ToastType toastType) {
            try {
                toastContext = new ToastContext();
                toastContext.Context = context;
                toastContext.ToastWidth = (int)getTextWidth(context, 16) + 20;
                toastContext.ToastWindowWidth = ((int)getTextWidth(context, 16) + 20 + 45);

                toast = new Toast();
                toastStrategy[toastType].Visibility = Visibility.Visible;
                toastStrategy.Clear();
                listToasts.Add(toast);
                toast.ShowInTaskbar = false;
                toast.WindowStartupLocation = WindowStartupLocation.CenterOwner;
                toast.Owner = App.Current.MainWindow;
                toast.Show();

                timer.Enabled = true;
                timer.AutoReset = false;
                timer.Interval = 3000;
                timer.Elapsed += destroy;
                timer.Start();
            } catch (Exception e) {
                logger.Error(e);
            }
        }

        /// <summary>
        /// 销毁Toast
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        public static void destroy(object source, ElapsedEventArgs e) {
            try {
                toast.Dispatcher.Invoke(()=> {
                    //foreach (Toast toast in listToasts) { toast.Close(); }
                    listToasts.ForEach((toast) => { toast.Close(); });
                    timer.Elapsed -= destroy;
                    timer.Stop();
                    timer.Close();
                });
            } catch (Exception ex) {
                logger.Error(ex);
            }
        }

        /// <summary>
        /// 计算特定字体及字体大小来计算文本长度
        /// </summary>
        /// <param name="text">计算的文本</param>
        /// <param name="fontSize">字体大小</param>
        /// <param name="fontFamily">特定的字体，默认为微软雅黑</param>
        /// <returns></returns>
        private static double getTextWidth(string text, double fontSize, string fontFamily = "微软雅黑") {
            FormattedText formattedText = new FormattedText(text, System.Globalization.CultureInfo.InvariantCulture, FlowDirection.LeftToRight, new Typeface(fontFamily.ToString()), fontSize, Brushes.Black);
            return formattedText.WidthIncludingTrailingWhitespace;
        }
    }

    /// <summary>
    /// Toast控件上下文
    /// </summary>
    public class ToastContext : INotifyPropertyChanged {
        /** 文本内容 */
        private string context;
        /** toast显示文本宽度 */
        private int toastWidth;
        /** toast窗体宽度 */
        private int toastWindowWidth;

        public int ToastWindowWidth {
            get { return toastWindowWidth; }
            set { toastWindowWidth = value; onPropertyChanged("ToastWindowWidth"); }
        }
        public int ToastWidth {
            get { return toastWidth; }
            set { toastWidth = value; onPropertyChanged("ToastWidth"); }
        }
        public string Context {
            get { return context; }
            set { context = value; onPropertyChanged("Context"); }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void onPropertyChanged(string propertyName) {

            if (PropertyChanged != null) {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }

        }
    }

    /// <summary>
    /// Toast类型
    /// </summary>
    public enum ToastType { 
        /** 错误 */
        error,
        /** 信息 */
        info
    }
}
